package com.cyh.generic;

/**
 * 子类也是泛型，子类和父类的泛型类型要一致
 * 子类不是是泛型，父类要明确泛型的数据类型
 * 泛型在创建对象的时候，没有指定类型，将按照Object类型来操作
 * 泛型扩展
 * 泛型接口， 实现类的规则跟类一样
 * 泛型方法
 *
 * 类的泛型不能作用于静态方法上。
 * 泛型方法的泛型可以作用于静态方法上
 *
 * 泛型方法的类型，是通过调用方法的时候来指定， 它的类型不受类的泛型类型的泛型影响， 即使类型名字一样
 *
 *
 * 泛型通配符
 * 函数中泛型参数不能重载
 * 类型通配符一般是使用 ？ 代替具体的类型实参， 所以，类型通配符是类型实参，而不是类型形参。
 * 泛型中： ? 表示可以传递任何类型的实参， 参数类型有传入的实参类型决定。
 * 泛型通配符的上限 ? extends Number ;  表示只可以传Number或Number的子类; ， 传参一般用上限
 *
 * 上限集合类不能add, add会报错, 所以需要下限
 *
 * 泛型通配符的下限 ？ super Integer; 表示只能是Integer类型或者他的父类型。
 *
 *
 * 不报错, 传参只能是Parent
 * public static void showBox(List<? super Parent> list) {
 *         list.add(new Child());
 *         list.add(new Parent());
 *     }
 *
 *
 *
 *
 * 第二个add报错, 传参可以是Child或者Parent
 * public static void showBox(List<? super Child> list) {
 *         list.add(new Child());
 *         list.add(new Parent());
 *     }
 *
 *
 * 两个add都报错, 传参可以是child或者Parent
 * public static void showBox(List<? extends Parent> list) {
 *         list.add(new Child());
 *         list.add(new Parent());
 *     }
 *
 *
 * 两个add都报错, 传参只能是Child
 * public static void showBox(List<? extends Child> list) {
 *         list.add(new Child());
 *         list.add(new Parent());
 *     }
 *
 *
 *
 * 编译完成后，泛型都会被擦除， class类型都是一样。通过反射得到的泛型都是Object, 有上限和下限的是上限和下限类型。
 *
 * 可以声明带泛型的数组引用，但是不能直接创建带泛型的数组对象
 * 错误代码如： ArrayList<String>[] listArr = new ArrayList<>[5];
 * 正确代码但是不合理，不能这么写，原因是list可以存int, 但是listArr却是String,如： ArrayList[] list = new ArrayList[5]; ArrayList<String>[] listArr = list;
 * 正确代码如： ArrayList<String>[] listArr = new ArrayList[5];
 *
 *
 * 可以通过java.lang.reflect.Array的newInstance(Class<T>, int)创建T[]数组。
 *
 *
 * 反射常用的泛型类
 * Class<T>
 * Constructor<T>
 * */
public class Test03 {
    public static void main(String[] args) {
        Generic<String> stringGeneric = new Generic<>("aaa"); //使用泛型
        Generic generic = new Generic("ABC"); //泛型在创建对象的时候，没有指定类型，将按照Object类型来操作
        if(stringGeneric.getClass() == generic.getClass()) {
            System.out.println("泛型的class是相同的");
        }

        GenericMethod genericMethod = new GenericMethod();
        //泛型方法的类型，是通过调用方法的时候来指定， 它的类型不受类的泛型类型的泛型影响， 即使类型名字一样
        Object o = genericMethod.getProduct(1);
        Integer i = genericMethod.getProduct(1);
        if(o.getClass() == o.getClass()) {
            System.out.println("两个泛型方法的类型是一样的");
        }



        Fruit<String> fruit = new Fruit<>(String.class, 3);
        fruit.put(0, "苹果");
        System.out.println(fruit.get(0));
    }
}
